/**
 * @description 渲染相关的逻辑
 */

const _ = require('lodash')
const { createSSRApp } = require('vue')
const { renderToString } = require('@vue/server-renderer')
const LowcodeComponents = require('@isameng/lowcode-components')
// const LegoComponents = require('lego-components')

/**
 * props 转换为 style
 * { 'backgroundRepeat': 'no-repeat', 'backgroundSize': 'cover' } => "background-repeat: no-repeat; background-size: cover"
 * @param {object} props props
 */
function propsToStyle(props = {}) {
  if (_.isEmpty(props)) return ''
  const keys = Object.keys(props)

  const styleArr = keys.map(key => {
    // backgroundRepeat => background-repeat  正则匹配出大写的字母，转化成 ’-小写字母‘ 例如 R => -r
    const formatKey = key.replace(/[A-Z]/g, c => `-${c.toLocaleLowerCase()}`)
    const value = props[key]
    return `${formatKey}: ${value}`
  })
  return styleArr.join(';')
}

/**
 * 将各个组件属性中的 px 改为 vw ，因为画布的宽度会影响定位的位置变化，所以需要将绝对的定位转换成相对的定位
 * 因为画布是按照宽度 375px 计算的，
 * 这里用到新的单位 vw（viewPort width）视口比例的长度
 * @param {Array} components 组件列表
 */
function px2vw(components = []) {
  const reg = /^(\d+(\.\d+)?)px$/ // 验证格式 '10px' '9.5px'
  // 遍历拿到组件的props属性
  components.forEach((component = {}) => {
    const props = component.props || {}
    // 遍历一个组件的属性
    _.forEach(props, (val, key) => {
      if (typeof val !== 'string') {
        return
      }
      if (reg.test(val) === false) {
        // val 中没有 px
        return
      }
      // val 中有 px
      const arr = val.match(reg) || [] // value 通过 match 匹配正则得到三组结果：例如：7.5px [7.5px, 7.5, .5]
      const numStr = arr[1] // 取出 '9.5'
      const num = parseFloat(numStr, 10)
      // 计算出 vw ，重新赋值
      // 编辑器画布宽度是 375 例如 left: 10px => 10 / 3.75 = 2.66 vw
      // 375px 按100份 vw 计算 1vw = 3.75px(375/100)，10px/3.75px = 2.66 vw
      // 在414px宽度的设备 2.66vw 转化成实际的像素 2.66 * 4.14 = 11px，是要比原来的10px更大的， 这就实现了适配不同尺寸的宽度
      let vwNum = num / (375 / 100) // 画布宽度是 375px ，这样计算出 vw
      vwNum = vwNum.toFixed(2) // 只保留 2 位小数
      props[key] = `${vwNum}vw`
    })
  })
}

/**
 * 渲染 lego-components
 * @param {Array} components 组件列表
 */
async function getComponentsHtml(components = []) {
  // 转换 px 到 vw ，以适应所有移动端手机尺寸
  px2vw(components)
  // vue ssr
  const app = createSSRApp({
    data: () => {
      const pageData = {
        // 页面上面一个个组件的属性
        components
      }
      return {
        pageData
      }
    },
    template: `<final-page :components="pageData.components"></final-page>`
  })
  app.use(LowcodeComponents) // 注册组件
  const html = await renderToString(app)
  return html
}

module.exports = {
  propsToStyle,
  getComponentsHtml
}
